package services;

import helpers.ConsoleConstants;
import helpers.ConsoleUtils;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Date;

import org.apache.commons.io.FilenameUtils;
import org.apache.http.client.utils.URIBuilder;

import models.Company;
import models.Project;
import models.Resource;
import models.ResourceType;
import models.Setting;

public class ProjectService extends ResourceService {

	private final SettingService settingService = SettingService.getService();

	private static ProjectService service;

	// Singleton pattern
	private ProjectService() {
	}

	/**
	 * The service instance.
	 * 
	 * @return The service instance
	 */
	public static ProjectService getService() {
		if (service == null) {
			service = new ProjectService();
		}
		return service;
	}

	/**
	 * Returns a project with a specified project name.
	 * 
	 * @param companyId
	 *            Company Id
	 * @param projectName
	 *            The project name
	 * @return The project of null if the project could not be found
	 */
	public Project getProject(long companyId, String projectName) {
		return Project.find.where().eq("company.id", companyId).eq("name", projectName).findUnique();
	}

	/**
	 * Saves a project.
	 * 
	 * @param project
	 *            The project
	 * @return The project
	 */
	public Project saveProject(Project project) {
		Project result = null;
		if (project.getId() <= 0) {
			result = createProject(project);
		} else {
			result = updateProject(project);
		}
		return result;
	}

	private Project createProject(Project project) {
		Date currentDate = new Date();
		project.setCreatedDate(currentDate);
		project.setLastModifiedDate(currentDate);
		project.save();

		createProjectDirectories(project);

		return project;
	}

	private Project updateProject(Project project) {
		project.setLastModifiedDate(new Date());
		project.save();

		createProjectDirectories(project);

		return project;
	}

	private void createProjectDirectories(Project project) {
		if (project != null) {
			String projectDirectory = getProjectDirectory(project);
			File directory = new File(projectDirectory);
			if (!directory.exists()) {
				directory.mkdirs();
			}

			directory = new File(ConsoleUtils.getPath(new String[] { projectDirectory, ConsoleConstants.CONFIGURATION_DIRECTORY }));
			if (!directory.exists()) {
				directory.mkdirs();
			}

			directory = new File(ConsoleUtils.getPath(new String[] { projectDirectory, ConsoleConstants.REPORTS_DIRECTORY }));
			if (!directory.exists()) {
				directory.mkdirs();
			}

			directory = new File(ConsoleUtils.getPath(new String[] { projectDirectory, ConsoleConstants.RESOURCES_DIRECTORY }));
			if (!directory.exists()) {
				directory.mkdirs();
			}

			directory = new File(ConsoleUtils.getPath(new String[] { projectDirectory, ConsoleConstants.TEST_SUITES_DIRECTORY }));
			if (!directory.exists()) {
				directory.mkdirs();
			}
		}
	}

	/**
	 * Initial Resource entity for default configuration of a project It will not create the entity in DB.
	 * 
	 * @param project
	 * @return
	 */
	public Resource initialDefaultConfiguration(Project project) {
		Resource config = new Resource(ResourceType.TestConfiguration, project, "Project configuration (" + project.getName() + ")");
		Date currentDate = new Date();
		config.setType(ResourceType.TestConfiguration);
		config.setCreatedDate(currentDate);
		config.setLastModifiedDate(currentDate);
		return config;
	}

	public String getProjectsRootDirectory(Company company) {
		String directory = null;
		if (company != null) {
			Setting setting = settingService.getSetting(Setting.CUSTOMERS_ROOT_DIRECTORY);
			if (setting != null) {
				directory = ConsoleUtils.getPath(new String[] { setting.getStringValue(), company.getCompanyId(), ConsoleConstants.PROJECTS_DIRECTORY });
			}
		}
		return directory;
	}

	public String getProjectDirectory(Project project) {
		String directory = null;
		if (project != null) {
			Setting setting = settingService.getSetting(Setting.CUSTOMERS_ROOT_DIRECTORY);
			if (setting != null) {
				directory = ConsoleUtils.getPath(new String[] { setting.getStringValue(), project.getCompany().getCompanyId(), ConsoleConstants.PROJECTS_DIRECTORY, Long.toString(project.getId()) });
			}
		}
		return directory;
	}

	public URL getTestExecuteURL(Project project, Resource config) throws MalformedURLException, URISyntaxException {
		URIBuilder builder = new URIBuilder(settingService.getSetting(Setting.TEST_EXECUTION_URL).getStringValue());
		builder.addParameter("companyid", ConsoleUtils.getCompany().getCompanyId());
		builder.addParameter("projectid", Long.toString(project.getId()));
		builder.addParameter("suite", "all");
		builder.addParameter("variablefile", FilenameUtils.getName(config.getResourcePath()));
		return builder.build().toURL();
	}

}
